Compile negated conditions as inverted jumps - #23292
Conversation
'if (!$x)', while/do-while conditions and ternaries with a top-level '!' emitted a BOOL_NOT into a temporary followed by JMPZ/JMPNZ - two dispatches and a TMP per evaluation, since without the opcache optimizer nothing rewrites it. Strip '!' layers in the condition and flip the jump opcode instead; both paths evaluate the operand with i_zend_is_true, so behavior including undefined-variable warnings is identical. This also lets comparisons under '!' fuse with the jump (smart branch), which BOOL_NOT previously prevented. Adjusts two opcode-dump tests for the changed temporary numbering.
'if (!$x)', while/do-while conditions and ternaries with a top-level '!' emitted a BOOL_NOT into a temporary followed by JMPZ/JMPNZ - two dispatches and a TMP per evaluation, since without the opcache optimizer nothing rewrites it. Strip '!' layers in the condition and flip the jump opcode instead; both paths evaluate the operand with i_zend_is_true, so behavior including undefined-variable warnings is identical. This also lets comparisons under '!' fuse with the jump (smart branch), which BOOL_NOT previously prevented. Adjusts two opcode-dump tests for the changed temporary numbering.
I'm not excited about increasing the complexity of the compiler for something that is already handled by the Optimizer. |
|
Same. It's probably possible to introduce a setting that compiles files with optimizations enabled for applications where it makes sense, even when opcache is disabled. Then, PHPStan can enable that setting in its root file. WDYT? |
Is there a reason to not run certain optimizations? I know this wasn't done as the optimizer used to be part of opcache, but now that it's not (and opcache is always bundled) it might make sense to just enable some unconditionally? |
|
It's more that optimizations take time, and while scripts in shm will run many times, scripts without shm will only run once. So the cost of running optimizations may exceed the cost of the script itself, especially if most code paths don't execute (e.g. imagine a Symfony command). But I don't know about concrete number and whether this line of reasoning actually makes sense. |
I guess this is something that might be worth exploring, but I think this requires to fully untie the Optimizer from opcache. |
disclaimer: this change was generated by claude opus. I have little experience with php-src development
'if (!$x)', while/do-while conditions and ternaries with a top-level '!' emitted a BOOL_NOT into a temporary followed by JMPZ/JMPNZ - two dispatches and a TMP per evaluation, since without the opcache optimizer nothing rewrites it. Strip '!' layers in the condition and flip the jump opcode instead; both paths evaluate the operand with i_zend_is_true, so behavior including undefined-variable warnings is identical. This also lets comparisons under '!' fuse with the jump (smart branch), which BOOL_NOT previously prevented.
Adjusts two opcode-dump tests for the changed temporary numbering.
note the improved
*_negatedvariantsafter PR
before PR
using negated_conditions_repro.php